/**
 * author: QuangMinh
 */
package vn.com.bookstore.utils;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import vn.com.bookstore.domain.model.PagingInfo;

@SuppressWarnings("serial")
public class PaginationTag extends TagSupport {
	private static final Logger logger = LoggerFactory
			.getLogger(PaginationTag.class);

	private PagingInfo pagingInfo;
	private String formId;
	private String pageIndexId;
	private boolean usingPageOverTotal = true;

	private final int edges = 2;
	private final int displayedPage = 5;

	public int doStartTag() throws JspException {

		int pageIndex = pagingInfo.getPageIndex();
		int totalPage = pagingInfo.getPageSize();
		StringBuilder pagingTemplate = new StringBuilder();
		// Show message result
		if (totalPage > 1 && usingPageOverTotal) {
			int toItem = pagingInfo.getPageIndex() * pagingInfo.getOffset();
			int fromItem = pagingInfo.getCurrentItemIndex();
			StringBuilder messagetag = new StringBuilder();
			messagetag.append("<div class='messgeResult'><span>Showing results ");
			if (pageIndex < totalPage) {
				messagetag.append(String.valueOf(fromItem));
				messagetag.append(" - ").append(String.valueOf(toItem));
			} else {
				messagetag.append(pagingInfo.getTotalItems());
			}
			messagetag.append(" of ").append(pagingInfo.getTotalItems())
					.append("</span></div>");
			pagingTemplate.append(messagetag);
		}

		// Show previous
		if (pageIndex == 1) {
			pagingTemplate.append("<span class='disabled'><< prev</span>");
		}

		if (pageIndex > 1) {
			pagingTemplate.append("<a href='")
					.append(buildAction(formId, pagingInfo.getPageIndex() - 1))
					.append("'><< prev</a>");
		}

		// Show number of page
		int start = getStart(pageIndex, totalPage);
		int end = getEnd(pageIndex, totalPage);
		// show start edges
		if (start > 0) {
			int endOfStartEdge = Math.min(edges, start);
			for (int i = 0; i < endOfStartEdge; i++) {
				pagingTemplate.append("<a href='")
						.append(buildAction(formId, i + 1)).append("'>")
						.append(i + 1).append("</a>");
			}
			if (edges < start && (start - edges) != 1) {
				pagingTemplate.append("...");
			} else if ((start - edges) == 1) {
				pagingTemplate.append("<a href='")
						.append(buildAction(formId, edges)).append("'>")
						.append(edges).append("</a>");
			}
		}
		// Show interval page in the middle
		for (int i = start; i < end; i++) {
			if (pageIndex == i+1) {
				pagingTemplate.append("<span class=\"current\">").append(i+1)
						.append("</span>");
			} else {
				pagingTemplate.append("<a href='")
						.append(buildAction(formId, i+1)).append("'>")
						.append(i+1).append("</a>");
			}
		}
		// Show end edges
		if (end < totalPage) {
			if ((totalPage - edges) > end && (totalPage - edges - end) != 1) {
				pagingTemplate.append("...");
			} else if (totalPage - edges - end == 1) {
				pagingTemplate.append("<a href='")
						.append(buildAction(formId, end++)).append("'>")
						.append(end++).append("</a>");
			}
			int begin = Math.max(totalPage - edges, end);
			for (int i = begin; i < totalPage; i++) {
				pagingTemplate.append("<a href='")
				.append(buildAction(formId, i + 1)).append("'>")
				.append(i + 1).append("</a>");
			}
		}

		// Show next
		if (pageIndex == totalPage) {
			pagingTemplate.append("<span class='disabled'>next >> </span>");
		}
		if (pageIndex < totalPage) {
			pagingTemplate.append("<a href='")
					.append(buildAction(formId, pagingInfo.getPageIndex() + 1))
					.append("'>next >></a>");
		}
		try {
			pageContext.getOut().print(pagingTemplate.toString());
		} catch (Exception e) {
			logger.info(e.getMessage());
		}
		return SKIP_BODY;
	}

	public int getStart(int currentPage, int totalPage) {
		int start = 0;
		int halfDisplayed = displayedPage / 2;
		if (currentPage > halfDisplayed) {
			start = Math.max(Math.min(currentPage - halfDisplayed, totalPage- displayedPage), 0);
		}

		return start;
	}

	public int getEnd(int currentPage, int totalPage) {
		int end = 0;
		int halfDisplayed = displayedPage / 2;
		if (currentPage > halfDisplayed) {
			end = Math.min(currentPage + halfDisplayed, totalPage);
		} else {
			end = Math.min(displayedPage, totalPage);
		}
		return end;
	}

	public String buildAction(String formId, int pageIndexValue) {
		String actionBuild = StringUtils.EMPTY;
		actionBuild = "javascript:submitForm(\"" + formId + "\", \""
				+ pageIndexId + "\", " + pageIndexValue + ");";
		return actionBuild;
	}

	/*
	 * GETTERS AND SETTERS
	 */
	public PagingInfo getPagingInfo() {
		return pagingInfo;
	}

	public void setPagingInfo(PagingInfo pagingInfo) {
		this.pagingInfo = pagingInfo;
	}

	public boolean isUsingPageOverTotal() {
		return usingPageOverTotal;
	}

	public void setUsingPageOverTotal(boolean usingPageOverTotal) {
		this.usingPageOverTotal = usingPageOverTotal;
	}

	public static Logger getLogger() {
		return logger;
	}

	public String getFormId() {
		return formId;
	}

	public void setFormId(String formId) {
		this.formId = formId;
	}

	public String getPageIndexId() {
		return pageIndexId;
	}

	public void setPageIndexId(String pageIndexId) {
		this.pageIndexId = pageIndexId;
	}
}
